#include "StdAfx.h"
#include "Surface.h"
#include "GraphicsLayer.h"
#include <iostream>

CSurface::CSurface(D3DXVECTOR3 v00,D3DXVECTOR3 v01,D3DXVECTOR3 v10,D3DXVECTOR3 v11)
{
	m_pVertexBuffer=NULL;
	m_pPatchIndexBuffer=NULL;

	m_iNumVertex=0;
	m_iNumPatches=0;
	m_Roll=0.0;
	m_Pitch=0.0;
	m_Yaw=0.0;
	m_x = 0.0;
	m_y = 0.0;
	m_z = 0.0;
	m_wire = false;
	m_CullNone = false;
	m_Texture = false;

	D3DXMatrixTranslation(&m_mTrans,m_x,m_y,m_z);

	D3DXMatrixIdentity(&m_mToWorldXFrom);
	D3DXMatrixRotationYawPitchRoll(&m_mRot,m_Yaw,m_Pitch,m_Roll);

	SetVertex(v00,v01,v10,v11);
	SetPatches();
	if(m_Texture)
		TextureMapping();
	CreateBuffers();

}

void CSurface::ResetMatrices()
{
	m_Roll=0.0;
	m_Pitch=0.0;
	m_Yaw=0.0;
	m_x = 0.0;
	m_y = 0.0;
	m_z = 0.0;

	D3DXMatrixTranslation(&m_mTrans,m_x,m_y,m_z);
	D3DXMatrixIdentity(&m_mToWorldXFrom);
	D3DXMatrixRotationYawPitchRoll(&m_mRot,m_Yaw,m_Pitch,m_Roll);
}
//------------------------------------------
CSurface::~CSurface(void)
{
}
//------------------------------
int CSurface::GetNumVerts(void)
{
	return m_iNumVertex;
}

//--------------------------------------
int CSurface::GetNumPatches()
{
	return  m_iNumPatches;
}
HRESULT CSurface::CreateBuffers()
{

	HRESULT hr = S_OK;
	D3D11_BUFFER_DESC DescBuffer;
	memset(&DescBuffer,0,sizeof(DescBuffer));
	D3D11_SUBRESOURCE_DATA resData;
	memset(&resData,0,sizeof(resData));

	//Settings for vertex buffer
	DescBuffer.Usage=D3D11_USAGE_DYNAMIC;
	DescBuffer.ByteWidth=sizeof(CSurfaceVertex)*GetNumVerts();
	DescBuffer.BindFlags= D3D11_BIND_VERTEX_BUFFER;
	DescBuffer.CPUAccessFlags=D3D11_CPU_ACCESS_WRITE;
	DescBuffer.MiscFlags=0;
	resData.pSysMem=&m_BoxVertex[0];
	hr=Graphics()->GetDevice()->CreateBuffer(&DescBuffer,&resData,&m_pVertexBuffer);
	if(hr!=S_OK)return hr;

	
	//Settings for Patch Index Buffer
	DescBuffer.Usage=D3D11_USAGE_DEFAULT;
	DescBuffer.ByteWidth=sizeof(WORD)*GetNumPatches()*16;
	DescBuffer.BindFlags=D3D11_BIND_INDEX_BUFFER;
	DescBuffer.CPUAccessFlags = 0;
	DescBuffer.MiscFlags = 0;
	resData.pSysMem=&m_PatchIndx[0];
	hr=Graphics()->GetDevice()->CreateBuffer(&DescBuffer,&resData,&m_pPatchIndexBuffer);
	

	return S_OK;
}

//-------------------------------------
void CSurface::DrawSmooth(int g_iTechniqueType)
{
	//actualize the transformations
	Graphics()->SetWorldMtx(m_mToWorldXFrom);
	if( m_wire )
	{
		if( m_CullNone )
			Graphics()->SetCullNoneWire();
		else
			Graphics()->SetCullBackWire();
	}
	else
		Graphics()->SetCullNone();
	Graphics()->SetSmooth(g_iTechniqueType);
	
	//get the buffers
	UINT uiStride=sizeof(CSurfaceVertex);
	UINT uiOffset=0;
	Graphics()->GetDeviceContext()->IASetVertexBuffers(0,1,&m_pVertexBuffer,&uiStride,&uiOffset);
	Graphics()->GetDeviceContext()->IASetIndexBuffer(m_pPatchIndexBuffer,DXGI_FORMAT_R16_UINT,0);
	Graphics()->GetDeviceContext()->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_4_CONTROL_POINT_PATCHLIST);
	
	Graphics()->UpdateMatrices();
	Graphics()->SetMatrices();
	Graphics()->GetDeviceContext()->DrawIndexed(GetNumPatches()*4,0,0);

}


void CSurface::SetVertex(D3DXVECTOR3 v00,D3DXVECTOR3 v01,D3DXVECTOR3 v10,D3DXVECTOR3 v11)
{
	m_BoxVertex[0].m_vPoint = v00;
	m_BoxVertex[1].m_vPoint = v01;
	m_BoxVertex[2].m_vPoint = v10;
	m_BoxVertex[3].m_vPoint = v11;

	m_iNumVertex = 4;
}

void CSurface::SetPatches()
{
	m_PatchIndx[0].v[0]=0;
	m_PatchIndx[0].v[1]=1;
	m_PatchIndx[0].v[2]=2;
	m_PatchIndx[0].v[3]=3;
	m_iNumPatches = 1;
}

void CSurface::Rotate(float r, float p, float y)
{
	m_Roll += r;
	m_Pitch += p;
	m_Yaw += y;

	D3DXMATRIX t;

	D3DXMatrixRotationYawPitchRoll(&m_mRot,y,p,r);

	float det = D3DXMatrixDeterminant(&m_mTrans);
	D3DXMatrixInverse(&t,&det,&m_mTrans);

	m_mToWorldXFrom *= t;
	m_mToWorldXFrom *= m_mRot;
	m_mToWorldXFrom *= m_mTrans;

	D3DXMatrixRotationYawPitchRoll(&m_mRot,m_Yaw,m_Pitch,m_Roll);
}

void CSurface::Translate(float x, float y, float z)
{
	m_x += x;
	m_y += y;
	m_z += z;

	D3DXMATRIX r;

	D3DXMatrixTranslation(&m_mTrans,x,y,z);
	
	float det = D3DXMatrixDeterminant(&m_mTrans);
	D3DXMatrixInverse(&r,&det,&m_mTrans);

	//m_mToWorldXFrom *= r;
	m_mToWorldXFrom *= m_mTrans;
	//m_mToWorldXFrom *= m_mRot;

	D3DXMatrixTranslation(&m_mTrans,m_x,m_y,m_z);
}

void CSurface::TextureMapping()
{
	D3DXVECTOR3 vNorm;
    float theta, phi;// sintheta;
	float u,v;

	for(int i=0;i<m_iNumVertex;i++)
	{
		
		D3DXVec3Normalize( &vNorm, &m_BoxVertex[i].m_vPoint);
        theta = acosf(vNorm.y);
        phi = atan2f(vNorm.x, vNorm.z);

        u = phi / 2.F / D3DX_PI + 0.5F;
		v = theta / D3DX_PI;
		u = (u > 0.5)?(1.F-u):(u);
				
		u *= 3.F;
		v *= 3.F;
		
		
		m_BoxVertex[i].m_vTexCord.x=u;
		m_BoxVertex[i].m_vTexCord.y=v;
	}
}